Skip to content

fix: support remote database hosts in health check#21

Merged
konradmichalik merged 3 commits intomainfrom
fix/health-check-remote-database
Feb 19, 2026
Merged

fix: support remote database hosts in health check#21
konradmichalik merged 3 commits intomainfrom
fix/health-check-remote-database

Conversation

@konradmichalik
Copy link
Contributor

@konradmichalik konradmichalik commented Feb 19, 2026

Summary

  • Use resolveDatabaseCredentials() in health check to connect to remote database servers via mysqladmin ping with host, port, and credentials
  • Skip pointless local pgrep check when database_host points to a remote server
  • Show meaningful error messages distinguishing remote connection failures from missing local processes

Changes

  • deployer/requirements/task/health.php - Resolve DB credentials and ping remote host; fall back to local process check only for local databases
  • README.md - Update standalone tasks links

Summary by CodeRabbit

  • Documentation

    • Updated a Standalone Tasks reference link in README.
  • Bug Fixes

    • Enhanced database health verification with credential-based checking and improved handling for local versus remote database hosts.

@konradmichalik
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

Updated README.md documentation link from Database management to Requirements in the Standalone Tasks section. Enhanced database health check logic in health.php with credential-based ping attempts, remote host detection, and conditional local process verification to determine database availability.

Changes

Cohort / File(s) Summary
Documentation
README.md
Updated Standalone Tasks link to point to Requirements instead of Database management.
Health Check Logic
deployer/requirements/task/health.php
Added credential-based database ping with remote host detection; introduced fallback behavior when credentials unavailable; conditional local process checks for localhost only; refined messaging to include hostInfo on successful credential pings and specific remote-unreachable messages.

Sequence Diagram

sequenceDiagram
    participant HC as Health Checker
    participant CR as Credential Resolver
    participant DB as Database
    participant LP as Local Process

    HC->>CR: resolveDatabaseCredentials()
    alt Credentials Found
        CR-->>HC: Return credentials + host info
        HC->>DB: Ping with credentials (host, port, user, password)
        alt Remote Host Detected
            DB-->>HC: Connection failed / unreachable
            HC->>HC: Log "Cannot reach remote host:port"
            HC-->>HC: Mark unhealthy
        else Local Host
            alt Ping Successful
                DB-->>HC: Success + hostInfo
                HC-->>HC: Mark healthy with hostInfo
            else Ping Failed
                HC->>LP: Check local mysqld/mariadbd process
                LP-->>HC: Process status
                HC-->>HC: Mark health based on process status
            end
        end
    else No Credentials
        HC->>DB: Fallback ping via mysqladmin
        alt Fallback Successful
            DB-->>HC: Success
            HC-->>HC: Mark healthy
        else Fallback Failed
            HC->>LP: Check local mysqld/mariadbd process
            LP-->>HC: Process status
            HC-->>HC: Mark health based on process status
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Credentials now checked with care and grace,
Remote hosts get their own special place,
Local or distant, the rabbit knows true,
Health checks refined, all shiny and new!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: support remote database hosts in health check' directly aligns with the main changes in the PR, which add remote database host support to the health check function.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/health-check-remote-database

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@deployer/requirements/task/health.php`:
- Around line 53-60: The current $pingCmd uses "--password=…" which exposes
credentials in the process table; instead create a temporary MySQL defaults file
on the remote host and supply it via --defaults-extra-file to the mysql client:
inside the Deployer run() sequence use run('mktemp') to get a safe remote path,
write a file containing a [client] section with user/host/port/password (use
escapeshellarg or printf with proper quoting when echoing to the remote file),
run the admin command using --defaults-extra-file=<tmp> (omit --password), then
securely remove the temp file with run('rm -f ' . escapeshellarg($tmpPath));
update references around $pingCmd and adminCmd to build the command this way and
ensure dbCredentials values are not embedded on the command line.
- Around line 69-83: The anonymous-socket fallback can produce a false positive
when credentials point to a remote host; update the logic so the fallback ping
is skipped for remote DBs by using the existing remote check before attempting
the socket ping: ensure the code that sets $isRemoteDb (based on $dbCredentials
host not being 'localhost', '127.0.0.1' or a socket) is present and then change
the fallback guard from "if (!$dbChecked)" to "if (!$dbChecked &&
!$isRemoteDb)"; this prevents run("$adminCmd ping --silent...") from marking the
DB healthy when the configured remote host failed earlier (refer to
$dbCredentials, $dbChecked, $isRemoteDb, run(), and addRequirementRow).

Comment on lines +53 to +60
$pingCmd = sprintf(
'%s ping --silent -h %s -P %d -u %s --password=%s 2>/dev/null',
$adminCmd,
escapeshellarg($dbCredentials['host']),
$dbCredentials['port'],
escapeshellarg($dbCredentials['user']),
escapeshellarg($dbCredentials['password'])
);
Copy link

@coderabbitai coderabbitai bot Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Password exposed in command-line argument (--password=…)

Using --password=password on the command line is convenient but insecure; on some systems the password becomes visible to status programs such as ps that may be invoked by other users to display command lines. The 2>/dev/null redirect only silences stderr — it does not mask the argument in the process table.

The safest approach is a temp --defaults-extra-file. A simpler middle-ground is a [client]-style option file written to a temp path, deleted immediately after the run() call. If the deployment context is trusted and the remote execution environment is sufficiently isolated, this risk may be acceptable, but it is worth an explicit acknowledgement.

🔒️ Suggested alternative: temp defaults file
-        $pingCmd = sprintf(
-            '%s ping --silent -h %s -P %d -u %s --password=%s 2>/dev/null',
-            $adminCmd,
-            escapeshellarg($dbCredentials['host']),
-            $dbCredentials['port'],
-            escapeshellarg($dbCredentials['user']),
-            escapeshellarg($dbCredentials['password'])
-        );
-
-        try {
-            run($pingCmd);
+        $tmpCnf = tempnam(sys_get_temp_dir(), 'deployer_db_');
+        $cnfContent = sprintf(
+            "[client]\nhost=%s\nport=%d\nuser=%s\npassword=%s\n",
+            $dbCredentials['host'],
+            $dbCredentials['port'],
+            $dbCredentials['user'],
+            $dbCredentials['password']
+        );
+        $pingCmd = sprintf(
+            '%s --defaults-extra-file=%s ping --silent 2>/dev/null',
+            $adminCmd,
+            escapeshellarg($tmpCnf)
+        );
+
+        try {
+            run(sprintf('printf %%s %s > %s', escapeshellarg($cnfContent), escapeshellarg($tmpCnf)));
+            run($pingCmd);

Note: The temp file must be created on the remote host (inside a Deployer run() call), not locally via tempnam(). Adjust accordingly for Deployer's remote execution model — e.g. generate a remote temp path with run('mktemp'), write the cnf, ping, then run('rm -f ' . escapeshellarg($tmpCnf)).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deployer/requirements/task/health.php` around lines 53 - 60, The current
$pingCmd uses "--password=…" which exposes credentials in the process table;
instead create a temporary MySQL defaults file on the remote host and supply it
via --defaults-extra-file to the mysql client: inside the Deployer run()
sequence use run('mktemp') to get a safe remote path, write a file containing a
[client] section with user/host/port/password (use escapeshellarg or printf with
proper quoting when echoing to the remote file), run the admin command using
--defaults-extra-file=<tmp> (omit --password), then securely remove the temp
file with run('rm -f ' . escapeshellarg($tmpPath)); update references around
$pingCmd and adminCmd to build the command this way and ensure dbCredentials
values are not embedded on the command line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai Valid point in general, but in this context the risk is acceptable: Deployer executes commands via short-lived SSH sessions, and other tasks in this project (e.g. check_database_grants.php, check_database.php) use the same CLI credential pattern. A temp defaults file would add disproportionate complexity (mktemp, write, cleanup, error handling) for a health-check ping. Acknowledged, but won't change.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@konradmichalik Understood — thank you for the context. Given the short-lived SSH session model and consistency with existing tasks in the repository, I agree the trade-off is reasonable for this use case. I've noted this pattern for future reference.


🧠 Learnings used
Learnt from: konradmichalik
Repo: move-elevator/deployer-tools PR: 11
File: deployer/typo3/task/feature_scheduler.php:15-15
Timestamp: 2026-02-18T10:07:30.947Z
Learning: In the move-elevator/deployer-tools repository, shell variables in `test()` and `runExtended()` calls are intentionally left unquoted as an established codebase convention. Deploy paths are server-configured and do not contain spaces, so defensive quoting is unnecessary and would be inconsistent with the existing pattern.

@konradmichalik konradmichalik merged commit ca66943 into main Feb 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments